/*******************************************************************************************
Copyright (C) 2016 Mestrelab Research S.L. All rights reserved.

This file is part of the Mnova scripting toolkit.

Authorized users of MNova Software may use this file freely, but this file is provided AS IS
with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE.
*******************************************************************************************/

/*globals mainWindow, nmr, settings, Application, MnUi, NMRSpectrum, MessageBox*/

/*jslint plusplus: true, continue: true, indent: 4*/

function centerSpectrumReference() {
	"use strict";

	var i, j, newLowestFrequency, spectralWidth, showDialog, dialog, defaultf1, parameters,
		lowestFrequency, checkParameters, notNumber, notNumberFound, dimension, defaultf2,
		spectrum, flagProblemReferencing, currentCenterFrequency, auxDefaultValues, spectra,
		centralFrequencyf1Key = "Center Spectrum Reference/Central Frequency for f1",
		centralFrequencyf2Key = "Center Spectrum Reference/Central Frequency for f2";

	//Get mandatory data
	spectrum = nmr.activeSpectrum();
	parameters = ["Spectral Width", "Lowest Frequency"];

	//Despite this initials asignments we will use the center point of the spectrum
	defaultf1 = 100;
	defaultf2 = 100;

	//Load UI and settings
	dialog = Application.loadUiFile('ricares:centerSpectrumReference.ui');

	//Check for an active spectrum
	if (!spectrum.isValid()) {
		MessageBox.critical("You need an active valid spectrum in order to launch the script.");
		return;
	}

	//Get all selected spectra
	spectra = centerSpectrumReference.getSelectedSpectra(spectrum.dimCount);

	//Check for valid parameters names
	for (i = 0; i < spectra.length; i++) {
		//Check for valid parameters names
		checkParameters = centerSpectrumReference.checkNeededParameters(parameters, spectra[i]);
		if (checkParameters !== "") {
			MessageBox.critical(checkParameters);
			return;
		}
	}

	//Get the center point of the spectrum
	auxDefaultValues = centerSpectrumReference.getCenterFrequency(parameters, spectrum, 100);
	if (auxDefaultValues.length === 1) {
		defaultf1 = auxDefaultValues[0];
	} else if (auxDefaultValues.length === 2) {
		defaultf2 = auxDefaultValues[0];
		defaultf1 = auxDefaultValues[1];
	}
	//Show an adapt GUI for 1D dimension
	dialog.show();
	dialog.widgets.dbCentralFrequencyf1.value = settings.value(centralFrequencyf1Key, defaultf1);
	dialog.widgets.dbCentralFrequencyf2.value = settings.value(centralFrequencyf2Key, defaultf2);
	if (spectrum.dimCount === 1) {
		dialog.widgets.lbCentralFrequencyf2.visible = false;
		dialog.widgets.dbCentralFrequencyf2.visible = false;
	}

	//Execute dialog
	showDialog = true;
	while (showDialog) {

		//Check if cancel button is pulsed by the user
		if (!dialog.exec()) {
			return;
		}

		if (spectrum.uuid === undefined || !spectrum.isValid()) {
			MessageBox.critical("You need an active valid spectrum in order to launch the script.");
			continue;
		} else {
			if (spectrum.dimCount === 1) {
				dialog.widgets.lbCentralFrequencyf2.visible = false;
				dialog.widgets.dbCentralFrequencyf2.visible = false;
				dialog.widgets.dbCentralFrequencyf2.value = settings.value(centralFrequencyf2Key, defaultf2);
			}
		}

		//Checking for valid parameter values
		notNumber = "There is not a valid value for the following parameters:\n";
		notNumberFound = false;
		for (i = 0; i < parameters.length; i++) {
			for (j = 0; j < spectrum.dimCount; j++) {
				dimension = j + 1;
				if (isNaN(spectrum.getParam(parameters[i] + "[" + dimension + "]"))) {
					notNumber += parameters[i] + "[" + dimension + "]\n";
					notNumberFound = true;
				}
			}
		}

		if (notNumberFound) {
			MessageBox.critical(notNumber);
			continue;
		}

		showDialog = false;
	}

	//Reference each spectrum for each dimension. Central Frequency = Lowest Frequency + Spectra Width / 2
	flagProblemReferencing = false;
	for (i = 0; i < spectra.length; i++) {
		spectrum = spectra[i];
		for (j = 0; j < spectrum.dimCount; j++) {
			dimension = j + 1;
			lowestFrequency =  spectrum.getParam(parameters[1] + "[" + dimension + "]");
			spectralWidth = spectrum.getParam(parameters[0] + "[" + dimension + "]");
			currentCenterFrequency = dialog.widgets.dbCentralFrequencyf1.value;
			if (spectrum.dimCount === 2 && dimension === 1) {
				currentCenterFrequency = dialog.widgets.dbCentralFrequencyf2.value;
			}
			if (isNaN(lowestFrequency) || isNaN(spectralWidth)) {
				flagProblemReferencing = true;
			} else {
				newLowestFrequency = currentCenterFrequency - (spectralWidth / 2);
				lowestFrequency = spectrum.unitsToUnits("Hz", "ppm", lowestFrequency, dimension);
				newLowestFrequency = spectrum.unitsToUnits("Hz", "ppm", newLowestFrequency, dimension);
				spectrum.reference(dimension, lowestFrequency, newLowestFrequency, false);
				spectrum.update();
			}
		}
	}

	if (flagProblemReferencing) {
		MessageBox.critical("There was a problem during the referencing process");
	} else {
		mainWindow.activeDocument.update();
	}

	//Save settings
	settings.setValue(centralFrequencyf1Key, dialog.widgets.dbCentralFrequencyf1.value);
	if (spectrum.dimCount === 2) {
		settings.setValue(centralFrequencyf2Key, dialog.widgets.dbCentralFrequencyf2.value);
	}
}

centerSpectrumReference.pageItemIsExpectedSpectrum = function (aDimension, aPageItem) {
	"use strict";

	var spectrum, result;

	result = false;
	if (aPageItem.name === "NMR Spectrum") {
		spectrum = new NMRSpectrum(aPageItem);
		if (spectrum.isValid() && spectrum.dimCount === aDimension) {
			result = true;
		}
	}

	return result;
};

centerSpectrumReference.getSelectedSpectra = function (aDimension) {
	"use strict";

	var  i, p, page, selItems, spectra, selPages, currentDocument, currentItem, currentSpectrum;

	selItems = [];
	spectra = [];
	currentDocument = mainWindow.activeDocument;
	selPages = currentDocument.selectedPages();

	if (selPages && selPages.length > 0) {
		for (p = 0; p < selPages.length; ++p) {
			for (i = 0; i < selPages[p].itemCount(); ++i) {
				currentItem = selPages[p].item(i);
				if (centerSpectrumReference.pageItemIsExpectedSpectrum(aDimension, currentItem)) {
					currentSpectrum = new NMRSpectrum(currentItem);
					spectra.push(currentSpectrum);
				}
			}
		}
	} else {
		selItems = currentDocument.selection();
		for (i = 0; i < selItems.length; i++) {
			currentItem = selItems[i];
			if (centerSpectrumReference.pageItemIsExpectedSpectrum(aDimension, currentItem)) {
				currentSpectrum = new NMRSpectrum(currentItem);
				spectra.push(currentSpectrum);
			}
		}

		if (selItems.length <= 0) {
			page = currentDocument.curPage();
			for (i = 0; i < page.itemCount(); ++i) {
				currentItem = page.item(i);
				if (centerSpectrumReference.pageItemIsExpectedSpectrum(aDimension, currentItem)) {
					currentSpectrum = new NMRSpectrum(currentItem);
					spectra.push(currentSpectrum);
				}
			}
		}
	}

	return spectra;
};

centerSpectrumReference.getCenterFrequency = function (aParameters, aSpectrum, aDefaultValue) {
	"use strict";

	var i, dimension, lowestFrequency, spectralWidth, centralFrequency, result;

	result = [];
	for (i = 0; i < aSpectrum.dimCount; i++) {
		dimension = i + 1;
		lowestFrequency = aSpectrum.getParam(aParameters[1] + "[" + dimension + "]");
		spectralWidth = aSpectrum.getParam(aParameters[0] + "[" + dimension + "]");
		if (!isNaN(lowestFrequency) && !isNaN(spectralWidth)) {
			centralFrequency =  lowestFrequency + (spectralWidth / 2);
			result.push(centralFrequency);
		} else {
			result.push(aDefaultValue);
		}
	}

	return result;
};

centerSpectrumReference.checkNeededParameters = function (aParameters, aSpectrum) {
	"use strict";

	var i, j, parameters, notFoundParameters, found, output;

	notFoundParameters = [];
	output = "";
	parameters = aSpectrum.paramNames();

	//Check if all parameters exist
	for (i = 0; i < aParameters.length; i++) {
		found = false;
		for (j = 0; j < parameters.length && !found; j++) {
			if (aParameters[i] === parameters[j]) {
				found = true;
			}
		}
		if (!found) {
			notFoundParameters.push(aParameters[i]);
		}
	}

	if (notFoundParameters.length === 1) {
		notFoundParameters += "The mandatory parameter " + aParameters[i] + " does not exist into the parameters table";
	} else if (notFoundParameters.length > 1) {
		output += "The following mandatory parameters do not exist into the parameters table:\n";
		for (i = 0; i < notFoundParameters.length; i++) {
			output += notFoundParameters[i];
			if (i !== notFoundParameters.length - 1) {
				output += "\n";
			}
		}
	}

	return output;
};

if (this.MnUi && MnUi.scripts_nmr) {
	MnUi.scripts_nmr.scripts_nmr_CenterSpectrumReference = centerSpectrumReference;
}
